package com.logic.landseaserver.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.logic.common.exception.BusinessException;
import com.logic.common.security.SecurityUtils;
import com.logic.common.util.QueryUtil;
import com.logic.landseaserver.common.LandeaConstants;
import com.logic.landseaserver.common.LandseaErrorMessageEnum;
import com.logic.landseaserver.common.enums.SystemCodeEnum;
import com.logic.landseaserver.common.exception.LandseaException;
import com.logic.landseaserver.common.util.DateUtil;
import com.logic.landseaserver.domain.BillPayment;
import com.logic.landseaserver.domain.Contract;
import com.logic.landseaserver.domain.WebankParam;
import com.logic.landseaserver.models.payment.PaymentConstant;
import com.logic.landseaserver.models.payment.PaymentConstant.PayType;
import com.logic.landseaserver.persistence.read.BillPaymentReadMapper;
import com.logic.landseaserver.persistence.read.ContractReadMapper;
import com.logic.landseaserver.persistence.read.WebankParamReadMapper;
import com.logic.landseaserver.persistence.write.BillPaymentWriteMapper;
import com.logic.landseaserver.service.IBillPaymentService;
import com.logic.landseaserver.service.IWeBankService;
import com.logic.landseaserver.service.bill.PaymentManager;
import com.logic.landseaserver.ws.dto.BillPaymentDTO;
import com.logic.landseaserver.ws.dto.CheckPayDTO;
import com.logic.landseaserver.ws.dto.WeBankPayDTO;
import com.logic.landseaserver.ws.dto.WeBankPayReqDTO;
import com.logic.landseaserver.ws.dto.WeBankPayRespDTO;
import com.logic.system.AppContext;

import net.sf.json.JSONObject;

/**
 * @Author: jack
 * @Date: 2017/5/4
 * @Description: 活动接口实现类
 */
@Service
public class BillPaymentServiceImpl implements IBillPaymentService
{
    @Autowired
    private AppContext appContext;
    
    @Autowired
    private BillPaymentReadMapper billPayReadMapper;
    
    @Autowired
    private BillPaymentWriteMapper billPayWriteMapper;
    
    @Autowired
    private IWeBankService weBankService;
    
    @Autowired
    private ContractReadMapper contractReadMapper;
    
    @Autowired
    private WebankParamReadMapper webankParamReadMapper;
    
    /**
     * 
     * [描述]：创建支付记录，要根据账单类型走不同的逻辑</br>
     *
     * @param paymentDTO
     * @return
     * @throws BusinessException
     * @throws LandseaException 
     *
     */
    @Override
    public Integer insertBillPaymentDTO(BillPaymentDTO paymentDTO)
        throws LandseaException
    {
        BillPayment billPayment = new BillPayment();
        // 转换成billPayment
        setBillPaymentByBillPaymentDTO(billPayment, paymentDTO);
        
        billPayment.setNeedCheckMoney(paymentDTO.isNeedCheckMoney());
        
        billPayment.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        
        Object handerObject = appContext.getBean(LandeaConstants.BILLTYPE_PREFIX + billPayment.getBillType());
        if (null == handerObject)
        {
            throw LandseaException.createException(LandseaErrorMessageEnum.BILLPAYMENT_BILLTYPE_ERROR);
        }
        PaymentManager paymentManager = (PaymentManager)handerObject;
        
        // 检查金额是否合法
        paymentManager.checkAmountMoney(billPayment);
        
        billPayWriteMapper.insertSelective(billPayment);
        return billPayment.getId();
    }
    
    @Override
    public void editBillPaymentDTO(BillPaymentDTO paymentDTO)
        throws BusinessException
    {
        BillPayment billPayment = billPayReadMapper.selectByPrimaryKey(paymentDTO.getId());
        setBillPaymentByBillPaymentDTO(billPayment, paymentDTO);
        billPayment.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        billPayWriteMapper.updateByPrimaryKeySelective(billPayment);
    }
    
    @Override
    public void deletePayment(Integer id)
        throws BusinessException
    {
        billPayWriteMapper.deleteByPrimaryKey(id);
    }
    
    // 通过orderDTO创建order
    public void setBillPaymentByBillPaymentDTO(BillPayment billPayment, BillPaymentDTO billPaymentDTO)
    {
        if (!StringUtils.isEmpty(billPaymentDTO.getBillId()))
        {
            billPayment.setBillId(billPaymentDTO.getBillId());
        }
        if (!StringUtils.isEmpty(billPaymentDTO.getPayType()))
        {
            billPayment.setPayType(billPaymentDTO.getPayType());
        }
        if (PayType.POS.equals(billPaymentDTO.getPayType()))
        {
            if ("".equals(billPaymentDTO.getTime()) || null == billPaymentDTO.getTime())
            {
                billPayment.setTime(new Date());
            }
            else
            {
                billPayment.setTime(billPaymentDTO.getTime());
            }
        }
        else
        {
            if (billPaymentDTO.getTime() != null)
            {
                billPayment.setTime(billPaymentDTO.getTime());
            }
        }
        
        if (!StringUtils.isEmpty(billPaymentDTO.getMoney()))
        {
            billPayment.setMoney(billPaymentDTO.getMoney());
        }
        if (!StringUtils.isEmpty(billPaymentDTO.getTransactionNo()))
        {
            billPayment.setTransactionNo(billPaymentDTO.getTransactionNo());
        }
        if (!StringUtils.isEmpty(billPaymentDTO.getOrderNo()))
        {
            billPayment.setOrderNo(billPaymentDTO.getOrderNo());
        }
        if (!StringUtils.isEmpty(billPaymentDTO.getBank()))
        {
            billPayment.setBank(billPaymentDTO.getBank());
        }
        if (!StringUtils.isEmpty(billPaymentDTO.getStatus()))
        {
            billPayment.setStatus(billPaymentDTO.getStatus());
        }
        if (!StringUtils.isEmpty(billPaymentDTO.getBillType()))
        {
            billPayment.setBillType(billPaymentDTO.getBillType());
        }
        
        if (!StringUtils.isEmpty(billPaymentDTO.getImageId()))
        {
            billPayment.setImageId(billPaymentDTO.getImageId());
        }
        if (!StringUtils.isEmpty(billPaymentDTO.getComments()))
        {
            billPayment.setComments((billPaymentDTO.getComments()));
        }
    }
    
    @Override
    public void delete(String arg0)
        throws BusinessException
    {
        
    }
    
    @Override
    public Object get(Integer arg0)
        throws BusinessException
    {
        return null;
    }
    
    @Override
    public int insert(Object arg0)
        throws BusinessException
    {
        return 0;
    }
    
    @Override
    public List<BillPaymentDTO> query(QueryUtil queryUtil)
    {
        List<BillPaymentDTO> result = billPayReadMapper.getBillPaymentList(queryUtil);
        return result;
    }
    
    @Override
    public void update(Object arg0)
        throws BusinessException
    {
        
    }
    
    @Override
    public Boolean validate(Object arg0)
        throws BusinessException
    {
        return null;
    }
    
    @Override
    public Boolean validateForDelete(Object arg0)
        throws BusinessException
    {
        return null;
    }
    
    @Override
    public Boolean validateForInsert(Object arg0)
        throws BusinessException
    {
        return null;
    }
    
    @Override
    public Boolean validateForUpdate(Object arg0)
        throws BusinessException
    {
        return null;
    }
    
    @Override
    public BillPayment getBillPayment(Integer billPaymentId)
    {
        BillPayment dto = billPayReadMapper.selectByPrimaryKey(billPaymentId);
        return dto;
    }
    
    /**
     * 
     * [描述]：事务已添加</br>
     *
     * @param payinfo
     * @return
     * @throws LandseaException
     * @throws Exception
     *
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {LandseaException.class,Exception.class})
    public WeBankPayRespDTO getBillWeBankPay(WeBankPayReqDTO payinfo)
        throws LandseaException, Exception
    {
        validateWebankPayDTO(payinfo);
        Integer billId = payinfo.getBillId();
        String billType = payinfo.getBillType();
        String payType = payinfo.getPayType();
        
        // 根据不同的账单类型获取合同
        Object handerObject = appContext.getBean(LandeaConstants.BILLTYPE_PREFIX + billType);
        if (null == handerObject)
        {
            throw LandseaException.createException(LandseaErrorMessageEnum.BILLPAYMENT_BILLTYPE_ERROR);
        }
        PaymentManager paymentManager = (PaymentManager)handerObject;
     // 根据不同的账单类型获取支付金额
        String price = paymentManager.getPrice(payinfo);
        payinfo.setPrice(price);

        // 插入账单
        String bankCode = "";
        if (PayType.WEBANK_ALIPAY.equals(payType) || PayType.WEBANK_WECHAT.equals(payType))
        {
            // 收单
            bankCode = "微众银行收单";
        }
        else if (PayType.WEBANK_MOBILE.equals(payType))
        {
            // 收银台
            bankCode = "微众银行收银台";
        }
        Date nowTime = new Date(System.currentTimeMillis());
        SimpleDateFormat sdFormatter = new SimpleDateFormat("yyyyMMddHHmmss");
        String reqTime = sdFormatter.format(nowTime);
        
        BillPaymentDTO billPaymentDTO = new BillPaymentDTO();
        billPaymentDTO.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        billPaymentDTO.setBank(bankCode);
        billPaymentDTO.setBillId(billId);
        billPaymentDTO.setMoney(Double.parseDouble(price));
        billPaymentDTO.setPayType(payType);
        billPaymentDTO.setStatus("BPST2"); // 未支付
        billPaymentDTO.setBillType(billType);
        Integer paymentId = insertBillPaymentDTO(billPaymentDTO);
        
        // 更新订单号
        BillPayment billPayment = new BillPayment();
        String orderNo = "E0" + reqTime + paymentId;
        billPayment.setId(paymentId);
        billPayment.setOrderNo(orderNo);
        billPayment.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        billPayWriteMapper.updateByPrimaryKeySelective(billPayment);
        
        //获取合同信息，获取项目对应的商户号等信息
        Contract contract = contractReadMapper.selectByPrimaryKey(paymentManager.getContractId(billId));
        if(contract==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_GETDETAIL_IS_NULL);
        }
        if (org.apache.commons.lang3.StringUtils.isEmpty(payType))
        {
            throw LandseaException.createException(LandseaErrorMessageEnum.WEBANK_PARAM_PAYTYPE_NULL);
        }
        WebankParam webankParam = webankParamReadMapper.selectByPrjId(contract.getProjectId());
        if(null == webankParam){
            throw LandseaException.createException(LandseaErrorMessageEnum.PROJECT_WEBANK_PARAM_NULL);
        }
        
        //组建接口参数类型
        WeBankPayDTO weBankPayDTO = new WeBankPayDTO();
        weBankPayDTO.setBusinessType("E0");
        weBankPayDTO.setGoodsName(payinfo.getBillType()+"账单");
        weBankPayDTO.setOrderId(orderNo);
        weBankPayDTO.setPrice(price);
        
        if (PayType.WEBANK_MOBILE.equals(payType))
        {
            if (contract.getUserId() == null)
            {
                throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_OFFLINE_UPDATE_USERID_ISNULL);
            }
            weBankPayDTO.setUserId(contract.getUserId());
        }
        
        WeBankPayRespDTO paydto = null;
        
        
        // 支付方式(网页)：微众-支付宝 
        if (PaymentConstant.PayType.WEBANK_ALIPAY.equals(payType))
        {
            if(null==webankParam.getQrAliMerchantId()){
                throw LandseaException.createException(LandseaErrorMessageEnum.WEBANKQR_PARAM_ALI_MERCHANTID_NULL);
            }
            weBankPayDTO.setMerchantId(webankParam.getQrAliMerchantId());
            if(null!=webankParam.getQrMerchantName())
            weBankPayDTO.setMerchantName(webankParam.getQrMerchantName());
            if(null!=webankParam.getQrMerchantAbbreviation())
            weBankPayDTO.setBrefMerchantName(webankParam.getQrMerchantAbbreviation());
            paydto = weBankService.getWeBankPayQR(weBankPayDTO);
        }
        // 支付方式(网页)：微众-微信
        else if (PaymentConstant.PayType.WEBANK_WECHAT.equals(payType))
        {
            // 微信
            if(null==webankParam.getQrMerchantId()){
                throw LandseaException.createException(LandseaErrorMessageEnum.WEBANKQR_PARAM_MERCHANTID_NULL);
            }
            weBankPayDTO.setMerchantId(webankParam.getQrMerchantId());
            if(null!=webankParam.getQrMerchantName())
            weBankPayDTO.setMerchantName(webankParam.getQrMerchantName());
            if(null!=webankParam.getQrMerchantAbbreviation())
            weBankPayDTO.setBrefMerchantName(webankParam.getQrMerchantAbbreviation());
            paydto = weBankService.getWeBankPayQR(weBankPayDTO);
        }
        // 支付方式(网页)：微众-收银台
        else if (PaymentConstant.PayType.WEBANK_MOBILE.equals(payType))
        {
            if(null==webankParam.getwMerchantId()){
                throw LandseaException.createException(LandseaErrorMessageEnum.WEBANK_PARAM_MERCHANTID_NULL);
            }
            if(null==webankParam.getwMerchantName()){
                throw LandseaException.createException(LandseaErrorMessageEnum.WEBANK_PARAM_MERCHANTNAME_NULL);
            }
            weBankPayDTO.setMerchantId(webankParam.getwMerchantId());
            weBankPayDTO.setMerchantName(webankParam.getwMerchantName());
            if(null!=webankParam.getwMerchantAbbreviation())
            weBankPayDTO.setBrefMerchantName(webankParam.getwMerchantAbbreviation());
            paydto = weBankService.getWeBankPay(weBankPayDTO);
        }
        
        return paydto;
    }

    
    public boolean validateWebankPayDTO(WeBankPayReqDTO payinfo) throws LandseaException{
        Integer billId = payinfo.getBillId();
        if (null == billId)
        {
            throw LandseaException.createException(LandseaErrorMessageEnum.BILL_INFO_BILL_ID_IS_NULL);
        }
        
        String billType = payinfo.getBillType();
        if (org.apache.commons.lang3.StringUtils.isEmpty(billType))
        {
            throw LandseaException.createException(LandseaErrorMessageEnum.WEBANK_PARAM_BILLTYPE_NULL);
        }
        return true;
    }
    
    @Override
    public String updatePayStatus(Integer billId)
        throws Exception
    {
        // Date date = DateUtils.addMinutes(new Date(), -ConstantChar.deposit_clear_time);
        Date date = null;
        List<String> errorMsg = new ArrayList<String>();
        List<String> excptionMsg = new ArrayList<String>();
        List<BillPayment> dto = billPayReadMapper.getUnpayedBillPayment(billId, date);
        for (int i = 0; i < dto.size(); i++)
        {
            BillPayment billPayment = dto.get(i);
            CheckPayDTO payinfo = new CheckPayDTO();
            
            payinfo.setBillPaymentId(billPayment.getId());
            payinfo.setBusinessType(SystemCodeEnum.BUSINESS_TYPE_BILLPAYMENT.getCode());
            try
            {
                weBankService.checkPay(payinfo);
            }
            catch (LandseaException e)
            {
                errorMsg.add("账单id" + billPayment.getId() + e.getErrorDesc());
            }
            catch (BusinessException e)
            {
                errorMsg.add("账单id" + billPayment.getId() + e.getMessage());
            }
            catch (Exception e2)
            {
                excptionMsg.add("账单id" + billPayment.getId() + e2.getMessage());
            }
        }
        JSONObject result = new JSONObject();
        result.put("status", 0);
        result.put("MSG", "已同步账单支付信息");
        result.put("BusinessException", errorMsg);
        result.put("ExceptionMSG", excptionMsg);
        return result.toString();
    }
    
    @Override
    public void clearBillPayment(Date date)
    {
        String comeDueDate = DateUtil.convertDateTime(date);
        billPayWriteMapper.clearBillPayment(comeDueDate);
    }
    
    @Override
    public void updateBillpayment(BillPayment billPayment)
    {
        billPayWriteMapper.updateByPrimaryKeySelective(billPayment);
    }
    
}
